package com.runrunfast.face.service.common;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.runrunfast.face.constant.ColourUrl;
import com.runrunfast.face.dao.DeviceRelationRepository;
import com.runrunfast.face.dao.PersonRelationRepository;
import com.runrunfast.face.entity.DeviceRelation;
import com.runrunfast.face.entity.PersonRelation;
import com.runrunfast.face.util.ColourProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

/**
 * 彩生活 Service
 *
 * @author YangNing
 */
@Service
public class ColourService {
    private Logger logger = LoggerFactory.getLogger(ColourService.class);

    @Resource
    ColourProperties colour;
    @Resource
    RestTemplate restTemplate;
    @Resource
    PersonRelationRepository personRelationRepository;
    @Resource
    DeviceRelationRepository deviceRelationRepository;

    /**
     * 上报Thing报文
     */
    public JSONObject reportThing(String thingId, String location, String deviceName) {
        long timestamp = System.currentTimeMillis() / 1000;
        String sign = getSign(timestamp);
        JSONObject data = new JSONObject();
        data.put("type", "Thing");
        data.put("system", "face");
        data.put("uid", getCmdNo());
        data.put("uuid", thingId);
        data.put("state", new JSONObject().put("status", "工作中"));

        JSONObject conf = new JSONObject();
        conf.put("communityUuid", "bcfe0f35-37b0-49cf-a73d-ca96914a46a5");
        conf.put("buildingUuid", "bcfe0f35-37b0-49cf-a73d-ca96914a46a5");
        conf.put("houseUuid", "bcfe0f35-37b0-49cf-a73d-ca96914a46a5");
        conf.put("unitUuid", "bcfe0f35-37b0-49cf-a73d-ca96914a46a5");
        conf.put("location", location);
        conf.put("deviceName", deviceName);
        data.put("conf", conf);

        JSONArray capacity = new JSONArray();
        capacity.add(JSONObject.parse("{\"name\":\"xxx/xxx/open\",\"describe\":\"打开识别功能\"}"));
        capacity.add(JSONObject.parse("{\"name\":\"xxx/xxx/open\",\"describe\":\"关闭识别功能\"}"));
        data.put("capacity", capacity);
        data.put("action", JSONObject.parse("{\"open\":{\"id\":\"id\",\"param1\":\"id\",\"param2\":\"xxxx\"},\"close\":{\"id\":\"id\",\"param1\":\"id\",\"param2\":\"xxxx\"}}"));

        MultiValueMap params = new LinkedMultiValueMap();
        params.add("data", data);
        params.add("fp", fingerPrint(data, timestamp, sign));
        ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(ColourUrl.HOST + ColourUrl.REPORT + "?ts=" + timestamp + "&sign=" + sign + "&appID=" + colour.getAppId(), params, JSONObject.class);
        return responseEntity.getBody();
    }

    /**
     * 上报Event报文
     */
    public JSONObject reportEvent(JSONObject callback) {
        long timestamp = System.currentTimeMillis() / 1000;
        String sign = getSign(timestamp);
        JSONObject data = new JSONObject();
        data.put("type", "Event");
        data.put("system", "face");
        data.put("uid", getCmdNo());

        DeviceRelation device = deviceRelationRepository.findByDeviceId("" + callback.getInteger("camera_id"));
        if (null == device) {
            return null;
        }
        data.put("uuid", device.getThingId());

        PersonRelation person = personRelationRepository.findByPersonId("" + callback.getInteger("person_id"));
        if (null == person) {
            return null;
        }

        JSONObject content = new JSONObject();
        content.put("accountUuid", person.getAccountUUid());
        content.put("time", callback.getString("recognize_time"));
        // TODO: 2018/5/21 设备id移动到外面的uuid字段
        data.put("content", content);
        MultiValueMap params = new LinkedMultiValueMap();
        params.add("data", data);
        params.add("fp", fingerPrint(data, timestamp, sign));
        ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(ColourUrl.HOST + ColourUrl.REPORT + "?ts=" + timestamp + "&sign=" + sign + "&appID=" + colour.getAppId(), params, JSONObject.class);
        return responseEntity.getBody();
    }

    /**
     * 调用用户信息微服务，根据手机号查询或新建用户
     */
    public JSONObject getAccountByPhone(String phone) {
        long timestamp = System.currentTimeMillis() / 1000;
        String sign = getSign(timestamp);
        ResponseEntity<JSONObject> responseEntity = restTemplate.getForEntity(ColourUrl.HOST + ColourUrl.USER_QUERY + "?ts=" + timestamp + "&sign=" + sign + "&appID=" + colour.getAppId() + "&access_token=" + getAccessToken(timestamp, sign) + "&mobile=" + phone, JSONObject.class);
        return responseEntity.getBody().getJSONObject("content");
    }

    /**
     * 根据手机号查询房屋信息(封装Thing报文用)
     */
    public JSONArray getHouseInfoByPhone(String phone) {
        long timestamp = System.currentTimeMillis() / 1000;
        String sign = getSign(timestamp);
        ResponseEntity<JSONObject> responseEntity = restTemplate.getForEntity(ColourUrl.HOST + ColourUrl.HOUSE_INFO + "?ts=" + timestamp + "&sign=" + sign + "&appID=" + colour.getAppId() + "&token=" + getAccessToken(timestamp, sign) + "&mobile=" + phone, JSONObject.class);
        return responseEntity.getBody().getJSONArray("content");
    }

    /**
     * 获取物体全局唯一的带时间戳编号
     */
    public String getCmdNo() {
        long timestamp = System.currentTimeMillis() / 1000;
        String sign = getSign(timestamp);
        // TODO: 2018/5/21 num参数没用at all
        MultiValueMap params = new LinkedMultiValueMap();
        //生成id的数量
        params.add("num", 1);
        ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(ColourUrl.HOST + ColourUrl.CMD_NO + "?ts=" + timestamp + "&sign=" + sign + "&appID=" + colour.getAppId(), params, JSONObject.class);
        return responseEntity.getBody().getJSONObject("content").getString("cmdno");
    }

    /**
     * 添加FingerPrint参数
     *
     * @param object
     * @param timestamp
     */
    private String fingerPrint(JSONObject object, Long timestamp, String sign) {
        JSONArray jsonArray = new JSONArray();
        jsonArray.add(object);
        MultiValueMap params = new LinkedMultiValueMap();
        params.add("data", object.toJSONString());
        ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(ColourUrl.HOST + ColourUrl.FINGER_PRINT + "?ts=" + timestamp + "&sign=" + sign + "&appID=" + colour.getAppId(), params, JSONObject.class);
        return responseEntity.getBody().getJSONObject("content").getString("fp");
    }

    /**
     * 获取鉴权2.0 token
     *
     * @return
     */
    private String getAccessToken(long timestamp, String sign) {
        String a = colour.getAppId() + timestamp + colour.getToken();
        String signature = DigestUtils.md5DigestAsHex(a.getBytes());
        MultiValueMap params = new LinkedMultiValueMap();
        // TODO: 2018/5/20 此处固定使用彩生活集团的corp_uuid
        params.add("corp_uuid", "a8c58297436f433787725a94f780a3c9");
        params.add("app_uuid", colour.getAppId());
        params.add("signature", signature);
        params.add("timestamp", timestamp);
        HttpEntity<MultiValueMap> requestEntity = new HttpEntity<>(params, null);
        ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(ColourUrl.HOST + ColourUrl.AUTH + "?ts=" + timestamp + "&sign=" + sign + "&appID=" + colour.getAppId(), HttpMethod.POST, requestEntity, JSONObject.class);
        String accessToken = responseEntity.getBody().getJSONObject("content").getString("accessToken");
        logger.info("accessToken--->: " + accessToken);
        return accessToken;
    }

    /**
     * 生成接口sign参数
     *
     * @param timestamp
     * @return
     */
    private String getSign(long timestamp) {
        String sign = DigestUtils.md5DigestAsHex((colour.getAppId() + timestamp + colour.getToken() + "false").getBytes());
        logger.info("sign--->: " + sign);
        return sign;
    }
}
